use std::str::FromStr;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Debug, Serialize, Clone)]
pub struct HandleStatus {
    pub id: i64,
    pub recv: String,
    pub status: Option<Status>,
    pub handle: Handle,
    pub data: Option<String>,
}

#[derive(Deserialize, Debug, Serialize, Clone)]
pub enum Handle {
    GetContainerList,
    CreateContainer,
    StartContainer,
    StopContainer,
    RemoveContainer,
    GetContainerStatus,
    GetImageList,
    RemoveImage,
    PullImage,
    RegisterInstance,
    CheckInstance,
    GetConfig,
    Other,
    Heartbeat,
    CreateExecute,
    StartExecute,
    RunCommand,
    RemoveExecute
}

#[derive(Deserialize, Debug, Serialize, Clone)]
pub enum Status {
    Waiting,
    Success,
    Fail,
    Unknown,
}

impl HandleStatus {

    pub fn from(handle_status: HandleStatus) -> Self {
        HandleStatus {
            id: handle_status.id.into(),
            recv: handle_status.recv.into(),
            status: Some(Status::Success),
            handle: handle_status.handle.into(),
            data: Some(String::new())
        }
    }

    pub fn new(id: i64, recv: String, handle: Handle) -> Self {
        HandleStatus {
            id,
            recv,
            status: Some(Status::Success),
            handle,
            data: Some(String::new())
        }
    }

    pub fn set_data<T: Serialize> (mut self, data: T) -> Self {
        if let Ok(data) = serde_json::to_string(&data) {
            self.data = Some(data);
        }
        self
    }
}

impl FromStr for Handle {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "/create/container" => {
                Ok(Handle::CreateContainer)
            }
            _ => {
                Ok(Handle::Other)
            }
        }
    }
}

